/*
 * 版权属于onps栈开发团队，遵循Apache License 2.0开源许可协议
 *
 */
#include <stdint.h>
#include "port/datatype.h"
#include "port/sys_config.h"
#include "onps_errors.h"
#include "port/os_datatype.h"
#include "port/os_adapter.h"
#include "one_shot_timer.h"
#include "onps_utils.h"
#include "protocols.h"
#include "onps_input.h"
#include "netif/netif.h"

#if NETTOOLS_TELNETSRV
#include "stm32f4xx.h"
#include "stm32f4x7_eth.h"

#if NETTOOLS_PING && NVTCMD_PING_EN
#include "sys_timer.h"
#endif //* #if NETTOOLS_PING && NVTCMD_PING_EN

#if SUPPORT_ETHERNET && NVTCMD_IFIP_EN
#include "at24c02.h"
#endif //* #if SUPPORT_ETHERNET && NVTCMD_IFIP_EN

#if NETTOOLS_SNTP && NVTCMD_NTP_EN
#include "rtc.h"
#endif //* #if NETTOOLS_SNTP && NVTCMD_NTP_EN

#define SYMBOL_GLOBALS
#include "telnet/os_nvt.h"
#undef SYMBOL_GLOBALS

#define THNVT_STK_SIZE 320 * 4
static const UCHAR l_ubaTHNvtPrio[NVTNUM_MAX] = {THNVT0_PRIO, THNVT1_PRIO}; 
static struct {
  rt_thread_t tid; 
  void *pvParam; 
} l_staTHNvt[NVTNUM_MAX]; 
extern void thread_nvt_handler(void *pvParam); 
void os_nvt_init(void)
{
  UCHAR i; 
  for(i=0; i<NVTNUM_MAX; i++)  
    l_staTHNvt[i].pvParam = NULL;   
}

void os_nvt_uninit(void)
{
}

BOOL os_nvt_start(void *pvParam)
{
  UCHAR i; 
  for(i=0; i<NVTNUM_MAX; i++)
  {
    if(NULL == l_staTHNvt[i].pvParam)
    {
      l_staTHNvt[i].tid = rt_thread_create("thread_nvt_handler", thread_nvt_handler, pvParam, THNVT_STK_SIZE, l_ubaTHNvtPrio[i], 5);  
      if(l_staTHNvt[i].tid != RT_NULL)
      {
        rt_thread_startup(l_staTHNvt[i].tid); 
        l_staTHNvt[i].pvParam = pvParam; 
        return TRUE; 
      }
    }
  }
  
  return FALSE; 
}

void os_nvt_stop(void *pvParam)
{
  UCHAR i; 
  for(i=0; i<NVTNUM_MAX; i++)
  {
    if(pvParam == l_staTHNvt[i].pvParam)
    {
      rt_thread_delete(l_staTHNvt[i].tid); 
      l_staTHNvt[i].pvParam = NULL; 
    }
  }
}

#if SUPPORT_ETHERNET && NVTCMD_IFIP_EN
#if ETH_EXTRA_IP_EN
BOOL os_nvt_add_ip(const CHAR *pszIfName, in_addr_t unIp, in_addr_t unSubnetMask)
{
  ST_ETHCFG_IP stEthCfg; 
  if(E2EthCfgReadIp(&stEthCfg))
  {
    CHAR i; 
    for(i=0; i<ETH_EXTRA_IP_NUM; i++)
    {
      if(!stEthCfg.staExtraIp[i].unAddr)
        break; 
    }    
      
    if(i < ETH_EXTRA_IP_NUM)
    {
      stEthCfg.staExtraIp[i].unAddr = unIp; 
      stEthCfg.staExtraIp[i].unSubnetMask = unSubnetMask; 
      
      return E2EthCfgUpdateIp((UCHAR *)&stEthCfg.staExtraIp[i], sizeof(ST_CFG_EXTRAIP), offsetof(ST_ETHCFG_IP, staExtraIp[i])); 
    }    
  }
  
  return FALSE;
}

BOOL os_nvt_del_ip(const CHAR *pszIfName, in_addr_t unIp)
{
  ST_ETHCFG_IP stEthCfg; 
  if(E2EthCfgReadIp(&stEthCfg))
  {
    CHAR i, bTargetIdx = -1; 
    for(i=0; i<ETH_EXTRA_IP_NUM; i++)
    {
      if(stEthCfg.staExtraIp[i].unAddr)
      {
        if (unIp == stEthCfg.staExtraIp[i].unAddr)         
          bTargetIdx = i;         
      }
      else
        break; 
    }
    
    if (bTargetIdx < 0)
        return TRUE; 
    
    //* 如果并不是最后一个ip地址存储单元，那么就需要把这之后的ip地址存储单元整体前移一个存储单元，达成实际的删除效果
    CHAR bCpyIpNum = i - (bTargetIdx + 1); 
    if (bCpyIpNum)
        memmove(&stEthCfg.staExtraIp[bTargetIdx], &stEthCfg.staExtraIp[bTargetIdx + 1], sizeof(ST_CFG_EXTRAIP) * bCpyIpNum);
    stEthCfg.staExtraIp[i - 1].unAddr = 0; 
      
    return E2EthCfgUpdateIp((UCHAR *)&stEthCfg.staExtraIp[bTargetIdx], sizeof(ST_CFG_EXTRAIP) * (bCpyIpNum + 1), offsetof(ST_ETHCFG_IP, staExtraIp[bTargetIdx])); 
  }
  
  return FALSE; 
}
#endif //* #if ETH_EXTRA_IP_EN 
BOOL os_nvt_set_ip(const CHAR *pszIfName, in_addr_t unIp, in_addr_t unSubnetMask, in_addr_t unGateway)
{
  struct {
    UINT unAddr;
    UINT unSubnetMask;
    UINT unGateway;
  } __attribute__((packed)) stNewAddr; 
  
  stNewAddr.unAddr = unIp; 
  stNewAddr.unSubnetMask = unSubnetMask; 
  stNewAddr.unGateway = unGateway; 
  
  return E2EthCfgUpdateIp((UCHAR *)&stNewAddr, sizeof(stNewAddr), 0); 
}

BOOL os_nvt_set_mac(const CHAR *pszIfName, const CHAR *pszMac)
{
  UCHAR ubaMacAddr[ETH_MAC_ADDR_LEN]; 
  netif_eth_ascii_to_mac(pszMac, ubaMacAddr); 
  if(E2EthCfgUpdateIp(ubaMacAddr, ETH_MAC_ADDR_LEN, offsetof(ST_ETHCFG_IP, ubaMacAddr)))
  {
    ETH_MACAddressConfig(ETH_MAC_Address0, ubaMacAddr); 
    return TRUE; 
  }
  
  return FALSE; 
}

BOOL os_nvt_set_dns(const CHAR *pszIfName, in_addr_t unPrimaryDns, in_addr_t unSecondaryDns)
{
  struct {
    UINT unPrimaryDNS;
    UINT unSecondaryDNS;
  } __attribute__((packed)) stDnsAddr; 
  
  stDnsAddr.unPrimaryDNS = unPrimaryDns; 
  stDnsAddr.unSecondaryDNS = unSecondaryDns; 
  
  return E2EthCfgUpdateIp((UCHAR *)&stDnsAddr, sizeof(stDnsAddr), offsetof(ST_ETHCFG_IP, unPrimaryDns));
}

BOOL os_nvt_set_dhcp(const CHAR *pszIfName)
{
  UINT unAddr = 0; 
  return E2EthCfgUpdateIp((UCHAR *)&unAddr, sizeof(unAddr), 0);  
}

void os_nvt_system_reset(void)
{
  NVIC_SystemReset(); 
}
#endif //* #if SUPPORT_ETHERNET && NVTCMD_IFIP_EN

#if NVTCMD_ROUTE_EN
BOOL os_nvt_add_route_entry(const CHAR *pszIfName, in_addr_t unDestination, in_addr_t unGenmask, in_addr_t unGateway)
{
  ST_ETHCFG_ROUTE_ENTRY stEntry; 
  stEntry.unDestination = unDestination;   
  stEntry.unGenmask = unGenmask; 
  stEntry.unGateway = unGateway; 
  
  return E2EthCfgWriteRouteEntry(&stEntry); 
}

BOOL os_nvt_del_route_entry(in_addr_t unDestination)
{
  ST_ETHCFG_ROUTE_ENTRY stEntry; 
  
  CHAR i; 
  for(i=0; i<ROUTE_ITEM_NUM; i++)
  {
    if(E2EthCfgReadRouteEntry(&stEntry, i))
    {
      if(unDestination == stEntry.unDestination) 
        return E2EthCfgDelRouteEntry(i); 
    }
  }  
  
  return TRUE;  
}
#endif //* #if NVTCMD_ROUTE_EN

#if NETTOOLS_PING && NVTCMD_PING_EN
UINT os_get_elapsed_millisecs(void)
{
  return GetElapsedMSecs(); 
}
#endif //* #if NETTOOLS_PING && NVTCMD_PING_EN

#if NETTOOLS_SNTP && NVTCMD_NTP_EN
void os_nvt_set_system_time(time_t tNtpTime)
{
  RTCSetSystemUnixTimestamp(tNtpTime); 
}
#endif //* #if NETTOOLS_SNTP && NVTCMD_NTP_EN

#endif //* #if NETTOOLS_TELNETSRV
